package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author Ys
 * @since 2023-08-12
 */
@Service
@Transactional
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {


    @Lazy
    @Autowired
    private IInteractionQuestionService questionService;


    //1. 将数据保存到回答评论表
    //2. 判断是回答还是评论
    //2-1 累加回答次数，更新到最新回复id
    //2-2 累加评论次数
    //3. 如果是学生提交，修改问题表状态为未查看
    // 新增回答或评论
    @Override
    public void saveReply(ReplyDTO replyDTO) {
      //1. 将数据保存到回答评论表
        //1-1 dto->po
        InteractionReply reply = BeanUtil.copyProperties(replyDTO, InteractionReply.class);
        //1-2 补充属性
        reply.setUserId(UserContext.getUser());
        //1-3 保存数据库
        this.save(reply);
        //2. 判断是回答还是评论
        if(replyDTO.getAnswerId() == null){
            //2-1 累加回答次数，更新最新回复id
            // update interaction_question set latest_answer_id=? and answer_times=answer_times+1 where id = ?
            questionService.lambdaUpdate()
                    .set(InteractionQuestion::getLatestAnswerId,reply.getQuestionId())
                    .setSql("answer_times=answer_times+1")
                    .eq(InteractionQuestion::getId,reply.getQuestionId())
                    .update();
        }else {
            //2-2 ；累加评论次数
            // update interaction_reply set reply_times=reply_times +1 where answer_id=?
            this.lambdaUpdate()
                    .setSql("reply_times=reply_times+1")
                    .eq(InteractionReply::getId,reply.getAnswerId())
                    .update();
        }
        //3. 如果是学生提交，修改问题表状态为未查看
        if(replyDTO.getIsStudent()){
            //update interaction_question set status=0 where id ?
            questionService
                    .lambdaUpdate()
                    .set(InteractionQuestion::getStatus,QuestionStatus.UN_CHECK)
                    .eq(InteractionQuestion::getId,reply.getQuestionId())
                    .update();
        }
    }

    @Autowired
    private UserClient userClient;

    @Autowired
    private RemarkClient remarkClient;

    //1. 分页条件查询
    //2. 根据userId+targetUserId查询用户信息，转Map
    //3.遍历回答或评论列表封装ReplyVO
    //4. 返回结果
    // 分页查询回答或评论
    @Override
    public PageDTO<ReplyVO> queryReplyPage(ReplyPageQuery pageQuery, boolean isAdmin) {
       //1. 分页条件查询
        //1-1 分页
        Page<InteractionReply> page = new Page<>(pageQuery.getPageNo(), pageQuery.getPageSize());
        //1-2 条件查询
        this.lambdaQuery()
                .eq(pageQuery.getQuestionId() != null,InteractionReply::getQuestionId,pageQuery.getQuestionId())
                .eq(pageQuery.getQuestionId() != null,InteractionReply::getAnswerId,0)// 查询回答列表
        .eq(pageQuery.getAnswerId() != null,InteractionReply::getAnswerId,pageQuery.getAnswerId())
                .orderByDesc(InteractionReply::getLikedTimes)
                .page(page);
        //1-3 如果没有回答或评论列表返回空对象
        List<InteractionReply> replyList = page.getRecords();
        if(CollUtil.isEmpty(replyList)){
            return PageDTO.empty(page);
        }
        //2. 根据userId+targetUserId查询用户信息，转Map集合
        //2-1 获取userId+targetUserId
        HashSet<Long> userIdSet = new HashSet<>();
        for (InteractionReply reccord : replyList) {
            userIdSet.add(reccord.getUserId());
            userIdSet.add(reccord.getTargetUserId());
        }
        //2-2 查询用户信息
        List<UserDTO> userDTOList = userClient.queryUserByIds(userIdSet);
        //2-3 转Map集合
        Map<Long, UserDTO> userDTOMap = userDTOList.stream().collect(Collectors.toMap(UserDTO::getId, userDTO -> userDTO));
        // 查询回答或评论是否被我(登录用户)点赞
        List<Long> bizIdList = replyList.stream().map(InteractionReply::getId).collect(Collectors.toList());
        Set<Long> bizIds = remarkClient.getLikedIds(bizIdList);
        //3. 遍历回答或评论列表封装ReplyVO
        ArrayList<ReplyVO> replyVOList = new ArrayList<>();
        for (InteractionReply reply : replyList) {
            //3-1 po->dto
            ReplyVO replyVO = BeanUtil.copyProperties(reply, ReplyVO.class);
            if(CollUtil.isNotEmpty(bizIds) && CollUtil.contains(bizIds,replyVO.getId())){
                replyVO.setLiked(true);
            }
            //3-2 如果不是匿名补充 回答者id 昵称、头像
            if(!reply.getAnonymity()){
                UserDTO userDTO = userDTOMap.get(reply.getUserId());
                replyVO.setUserName(userDTO.getName());
                replyVO.setUserIcon(userDTO.getIcon());
                replyVO.setUserType(userDTO.getType());
            }
            //3-3 补充被评论用户的昵称
            UserDTO targetUserDTO = userDTOMap.get(reply.getTargetUserId());
            replyVO.setTargetUserName(targetUserDTO.getName());//被评论的是谁
            //3-4添加voList
            replyVOList.add(replyVO);
        }
        //4. 返回结果
        return PageDTO.of(page,replyVOList);
    }
}
